home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / comm1 / mgplp378.lha / magplip / source / device.c < prev    next >
C/C++ Source or Header  |  1996-05-13  |  27KB  |  814 lines

  1. /*
  2. ** $VER: device.c 1.12 (13 May 1996)
  3. **
  4. ** magplip.device - Parallel Line Internet Protocol
  5. **
  6. ** Original code written by Oliver Wagner and Michael Balzer.
  7. **
  8. ** This version has been completely reworked by Marius Gröger, introducing
  9. ** slight protocol changes. The new source is a lot better organized and
  10. ** maintainable.
  11. **
  12. ** Additional changes and code cleanup by Jan Kratochvil and Martin Mares.
  13. ** The new source is significantly faster and yet better maintainable.
  14. **
  15. ** (C) Copyright 1993-1994 Oliver Wagner & Michael Balzer
  16. ** (C) Copyright 1995 Jan Kratochvil & Martin Mares
  17. ** (C) Copyright 1995-1996 Marius Gröger
  18. **     All Rights Reserved
  19. **
  20. ** $HISTORY:
  21. **
  22. ** 13 May 1996 : 001.012 :  unit wasn't dealt with properly,
  23. **                          fixed by Detlef Wuerkner <tetisoft@apg.lahn.de>
  24. ** 29 Mar 1996 : 001.011 :  changed copyright note
  25. ** 29 Dec 1995 : 001.010 :  + taglist of CreateNewProcTags() wasn't
  26. **                            properly ended
  27. **                          + FreeSignal() missing
  28. **                          + better error check on child task launch
  29. ** 03 Sep 1995 : 001.009 :  hardware addressing nicer
  30. ** 30 Aug 1995 : 001.008 :  minor declaration related changes
  31. ** 20 Aug 1995 : 001.007 :  just bumped for new header, no code changes
  32. ** 05 Aug 1995 : 001.006 :  finally compiles w/out warnings :)
  33. ** 25 Apr 1995 : 001.005 :  now compiles with ANSI and STRICT
  34. ** 08 Mar 1995 : 001.004 :  now handles directly write reqs, the server
  35. **                          task is just signalled
  36. ** 05 Mar 1995 : 001.003 :  S2_DEVICEQUERY was desastrously broken
  37. ** 04 Mar 1995 : 001.002 :  using SANA2IOF_QUICK instead IOF_QUICK
  38. ** 18 Feb 1995 : 001.001 :  using BASEPTR
  39. **                          PLIPBase is cleared in DevInit()
  40. **                          now rejects all r/w-requests without BuffMgmt
  41. ** 12 Feb 1995 : 001.000 :  reworked original
  42. */
  43.  
  44. #define DEBUG 0
  45.  
  46. /*F*/ /* includes */
  47. #ifndef CLIB_ALIB_PROTOS_H
  48. #include <clib/alib_protos.h>
  49. #endif
  50. #ifndef CLIB_EXEC_PROTOS_H
  51. #include <clib/exec_protos.h>
  52. #include <pragmas/exec_sysbase_pragmas.h>
  53. #endif
  54. #ifndef CLIB_DOS_PROTOS_H
  55. #include <clib/dos_protos.h>
  56. #include <pragmas/dos_pragmas.h>
  57. #endif
  58. #ifndef CLIB_CIA_PROTOS_H
  59. #include <clib/cia_protos.h>
  60. #include <pragmas/cia_pragmas.h>
  61. #endif
  62. #ifndef CLIB_MISC_PROTOS_H
  63. #include <clib/misc_protos.h>
  64. #include <pragmas/misc_pragmas.h>
  65. #endif
  66. #ifndef CLIB_UTILITY_PROTOS_H
  67. #include <clib/utility_protos.h>
  68. #include <pragmas/utility_pragmas.h>
  69. #endif
  70. #ifndef CLIB_TIME_PROTOS_H
  71. #include <clib/timer_protos.h>
  72. #include <pragmas/timer_pragmas.h>
  73. #endif
  74. #ifndef DEVICES_SANA2_H
  75. #include <devices/sana2.h>
  76. #endif
  77.  
  78. #ifndef HARDWARE_CIA_H
  79. #include <hardware/cia.h>
  80. #endif
  81.  
  82. #ifndef DOS_DOSTAGS_H
  83. #include <dos/dostags.h>
  84. #endif
  85.  
  86. #ifndef RESOURCES_MISC_H
  87. #include <resources/misc.h>
  88. #endif
  89.  
  90. #ifndef EXEC_MEMORY_H
  91. #include <exec/memory.h>
  92. #endif
  93.  
  94. #ifndef _STRING_H
  95. #include <string.h>
  96. #endif
  97.  
  98. #ifndef __MAGPLIP_H
  99. #include "magplip.h"
  100. #endif
  101. #ifndef __DEBUG_H
  102. #include "debug.h"
  103. #endif
  104. #ifndef __COMPILER_H
  105. #include "compiler.h"
  106. #endif
  107. /*E*/
  108.  
  109. /*F*/ /* imports */
  110. PUBLIC VOID SAVEDS ServerTask(VOID);
  111. PUBLIC BOOL remtracktype(BASEPTR, ULONG type);
  112. PUBLIC BOOL addtracktype(BASEPTR, ULONG type);
  113. PUBLIC BOOL gettrackrec(BASEPTR, ULONG type, struct Sana2PacketTypeStats *info);
  114. PUBLIC VOID dotracktype(BASEPTR, ULONG type, ULONG ps, ULONG pr, ULONG bs, ULONG br, ULONG pd);
  115. PUBLIC VOID freetracktypes(BASEPTR);
  116. #define min __builtin_min
  117. /*E*/
  118. /*F*/ /* exports */
  119. PUBLIC ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase);
  120. PUBLIC ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR);
  121. PUBLIC ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR);
  122. PUBLIC ASM SAVEDS BPTR DevClose( REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  123. PUBLIC VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2);
  124. PUBLIC ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR);
  125. PUBLIC ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  126. /*E*/
  127. /*F*/ /* private */
  128. PRIVATE BOOL isinlist(struct Node *n, struct List *l);
  129. PRIVATE VOID abort(BASEPTR, struct IOSana2Req *ior);
  130. /*E*/
  131.  
  132.    /*
  133.    ** various support routines
  134.    */
  135. /*F*/ PRIVATE BOOL isinlist(struct Node *n, struct List *l)
  136. {
  137.    struct Node *cmp;
  138.  
  139.    for(cmp = l->lh_Head; cmp->ln_Succ; cmp = cmp->ln_Succ)
  140.       if (cmp == n) return TRUE;
  141.    
  142.    return FALSE;
  143. }
  144. /*E*/
  145. /*F*/ PRIVATE VOID abort(BASEPTR, struct IOSana2Req *ior)
  146. {
  147.    Remove((struct Node*)ior);
  148.    ior->ios2_Req.io_Error = IOERR_ABORTED;
  149.    ior->ios2_WireError = 0;
  150.    ReplyMsg((struct Message*)ior);
  151. }
  152. /*E*/
  153.  
  154.    /*
  155.    ** initialise device
  156.    */
  157. /*F*/ PUBLIC ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase)
  158. {
  159.    BOOL ok;
  160.    UBYTE *p;
  161.    UWORD i;
  162.  
  163.    d(("entered device, initialising PLIPBase...\n"));
  164.  
  165.       /* clear data base */
  166.    for(p = ((UBYTE*)pb) + sizeof(struct Library), i = sizeof(struct PLIPBase)-sizeof(struct Library); i; i--)
  167.       *p++ = 0;
  168.  
  169.    SysBase = _SysBase;
  170.  
  171.    pb->pb_SegList = seglist;           /* store DOS segment list */
  172.  
  173.       /* init some default values */
  174.    pb->pb_MTU = PLIP_DEFMTU;
  175.    pb->pb_ReportBPS = PLIP_DEFBPS;
  176.    pb->pb_Retries = PLIP_DEFRETRIES;
  177.    pb->pb_Flags = PLIPF_NOTCONFIGURED | PLIPF_OFFLINE;
  178.    pb->pb_Timeout = PLIP_DEFTIMEOUT;
  179.  
  180.       /* set signal to unallocated state */
  181.    pb->pb_IntSig = (ULONG)-1;
  182.  
  183.       /* initialise the lists */
  184.    NewList((struct List*)&pb->pb_ReadList);
  185.    NewList((struct List*)&pb->pb_WriteList);
  186.    NewList((struct List*)&pb->pb_EventList);
  187.    NewList((struct List*)&pb->pb_ReadOrphanList);
  188.    NewList((struct List*)&pb->pb_TrackList);
  189.    NewList((struct List*)&pb->pb_BufferManagement);
  190.  
  191.       /* initialise the access protection semaphores */
  192.    InitSemaphore(&pb->pb_ReadListSem);
  193.    InitSemaphore(&pb->pb_ReadOrphanListSem);
  194.    InitSemaphore(&pb->pb_EventListSem);
  195.    InitSemaphore(&pb->pb_WriteListSem);
  196.    InitSemaphore(&pb->pb_TrackListSem);
  197.    InitSemaphore(&pb->pb_Lock);
  198.  
  199.    pb->pb_SpecialStats[S2SS_TXERRORS].Type = S2SS_PLIP_TXERRORS;
  200.    pb->pb_SpecialStats[S2SS_TXERRORS].Count = 0;
  201.    pb->pb_SpecialStats[S2SS_TXERRORS].String = "TX Errors";
  202.    pb->pb_SpecialStats[S2SS_COLLISIONS].Type = S2SS_PLIP_COLLISIONS;
  203.    pb->pb_SpecialStats[S2SS_COLLISIONS].Count = 0;
  204.    pb->pb_SpecialStats[S2SS_COLLISIONS].String = "Collisions";
  205.  
  206.    ok = FALSE;
  207.  
  208.    if (UtilityBase = OpenLibrary("utility.library", 37))
  209.    {
  210.       if (DOSBase = OpenLibrary("dos.library", 37))
  211.       {
  212.          ok = TRUE;
  213.       }
  214.       else
  215.       {
  216.          d(("no dos\n"));
  217.       }
  218.  
  219.       if (!ok) CloseLibrary(UtilityBase);
  220.    }
  221.    else
  222.    {
  223.       d(("no utility\n"));
  224.    }
  225.  
  226.    d(("left %ld\n",ok));
  227.  
  228.    return (struct Device *)(ok ? pb : NULL);
  229. }
  230. /*E*/
  231.  
  232.    /*
  233.    ** open device
  234.    */
  235. /*F*/ PUBLIC ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR)
  236. {
  237.    BOOL ok = FALSE;
  238.    struct BufferManagement *bm;
  239.    LONG rv;
  240.  
  241.    d(("entered\n"));
  242.  
  243.    /* Make sure our open remains single-threaded. */
  244.    ObtainSemaphore(&pb->pb_Lock);
  245.  
  246.    pb->pb_DevNode.lib_OpenCnt++;
  247.  
  248.    /* not promiscouos mode and unit valid ? */
  249.    if (!(flags & SANA2OPF_PROM) && ((unit == 0) || (unit == 1)))
  250.    {
  251.       /* Allow access only if NOT:
  252.       **
  253.       **    Anybody else has already opened it AND
  254.       **          the current access is exclusive
  255.       **       OR the first access was exclusive
  256.       **       OR this access wants a different unit
  257.       */
  258.  
  259.       if (!((pb->pb_DevNode.lib_OpenCnt > 1) &&
  260.             ((flags & SANA2OPF_MINE)
  261.           || (pb->pb_Flags & PLIPF_EXCLUSIVE)
  262.           || (unit != pb->pb_Unit))))
  263.       {
  264.          if (flags & SANA2OPF_MINE)
  265.             pb->pb_Flags |= PLIPF_EXCLUSIVE;
  266.          else
  267.             pb->pb_Flags &= ~PLIPF_EXCLUSIVE;
  268.          
  269.          /*
  270.          ** 13.05.96: Detlef Wuerkner <TetiSoft@apg.lahn.de>
  271.          ** Rememer unit of 1st OpenDevice()
  272.          */
  273.          if (pb->pb_DevNode.lib_OpenCnt == 1)
  274.             pb->pb_Unit = unit;
  275.  
  276.          /*
  277.          ** The origninal "client/server" scheme was unfortune. I guess this
  278.          ** resulted out of the (also very unfortune) wiring: POUT->POUT,
  279.          ** BUSY->BUSY. Had the creators chosen this connection to be crossed
  280.          ** over, a completely symmetrical driver would have been possible.
  281.          ** My new approach does the (in either case) neccessary crossing
  282.          ** by software. The PLIPBase->HandshakeXXX[] arrays are initialised
  283.          ** here so that the actual communication code are no longer bothered.
  284.          */
  285.          if (unit)
  286.          {
  287.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRPOUT;
  288.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRBUSY;
  289.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRPOUT;
  290.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRBUSY;
  291.             pb->pb_SrcAddr[0] = 0x80;
  292.             pb->pb_DstAddr[0] = 0x00;
  293.          }
  294.          else
  295.          {
  296.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRBUSY;
  297.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRPOUT;
  298.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRBUSY;
  299.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRPOUT;
  300.             pb->pb_SrcAddr[0] = 0x00;
  301.             pb->pb_DstAddr[0] = 0x80;
  302.          }
  303.  
  304.          /*
  305.          ** Each opnener get's it's own BufferManagement. This is neccessary
  306.          ** since we want to allow several protocol stacks to use PLIP
  307.          ** simultaneously.
  308.          */
  309.          if (bm = AllocVec(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  310.          {
  311.             /*
  312.             ** We don't care if there actually are buffer management functions,
  313.             ** because there might be openers who just want some statistics
  314.             ** from us.
  315.             */
  316. #if defined(__SASC) && (__VERSION__ == 6) && (__REVISION__ == 56)
  317.             /* Jippieee! */
  318.             bm->bm_CopyToBuffer = (BMFunc)GetTagData(S2_CopyToBuff, NULL,
  319.                               (struct TagItem *)ios2->ios2_BufferManagement);
  320.             bm->bm_CopyFromBuffer = (BMFunc)GetTagData(S2_CopyFromBuff, NULL,
  321.                               (struct TagItem *)ios2->ios2_BufferManagement);
  322. #else
  323.             /*
  324.             ** The type casting below is very beautiful. This is a SAS/C bug:
  325.             ** I have to cast the ULONG that I got from GetTagData() to a
  326.             ** (void (*)(void)) function pointer. Now I may cast it to (BMFunc),
  327.             ** which defines the __asm and register stuff.
  328.             **
  329.             ** I would call this a cast with ``soft force'', as it seems that
  330.             ** I slowly have to make the ULONG being used to the fact of
  331.             ** becoming a pointer (``Look, old mathematical chap: didn't you
  332.             ** always want to be a pointer? Did you know how less it takes, how
  333.             ** mighty the dark side of the force really is?'').
  334.             */
  335.             bm->bm_CopyToBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyToBuff, NULL,
  336.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  337.             bm->bm_CopyFromBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyFromBuff, NULL,
  338.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  339. #endif
  340.             d(("starting servertask\n"));
  341.             if (!pb->pb_Server)
  342.             {
  343.                volatile struct ServerStartup ss;
  344.                struct MsgPort *port;
  345.  
  346.                if (port = CreateMsgPort())
  347.                {
  348.                   d(("starting server"));
  349.                   if (pb->pb_Server = CreateNewProcTags(NP_Entry, ServerTask, NP_Name,
  350.                                                                   SERVERTASKNAME, TAG_DONE))
  351.                   {
  352.                      ss.ss_Error = 1;
  353.                      ss.ss_PLIPBase = pb;
  354.                      ss.ss_Msg.mn_Length = sizeof(ss);
  355.                      ss.ss_Msg.mn_ReplyPort = port;
  356.                      d(("passing startup msg, pb is %lx\n", pb));
  357.                      PutMsg(&pb->pb_Server->pr_MsgPort, (struct Message*)&ss);
  358.                      WaitPort(port);
  359.  
  360.                      if (!ss.ss_Error)
  361.                         ok = TRUE;
  362.                      else
  363.                      {
  364.                         d(("server task failed\n"));
  365.                      }
  366.                   }
  367.                   else
  368.                   {
  369.                      d(("couldn't launch server task\n"));
  370.                   }
  371.                   DeleteMsgPort(port);
  372.                }
  373.                else
  374.                {
  375.                   d(("no temp-message port for server startup\n"));
  376.                }
  377.             }
  378.             else ok = TRUE;
  379.  
  380.             if (!ok)
  381.                FreeVec(bm);
  382.             else
  383.             {
  384.                /* enqueue buffer management into list
  385.                */
  386.                AddTail((struct List *)&pb->pb_BufferManagement,(struct Node *)bm);
  387.                pb->pb_DevNode.lib_OpenCnt++;
  388.                pb->pb_DevNode.lib_Flags &= ~LIBF_DELEXP;
  389.                ios2->ios2_BufferManagement = (VOID *)bm;
  390.                ios2->ios2_Req.io_Error = 0;
  391.                ios2->ios2_Req.io_Unit = (struct Unit *)unit;
  392.                ios2->ios2_Req.io_Device = (struct Device *)pb;
  393.                rv = 0;
  394.             }
  395.          }
  396.       }
  397.    }
  398.  
  399.       /* See if something went wrong. */
  400.    if(!ok)
  401.    {
  402.       ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  403.       ios2->ios2_Req.io_Unit = (struct Unit *) 0;
  404.       ios2->ios2_Req.io_Device = (struct Device *) 0;
  405.       rv = IOERR_OPENFAIL;
  406.    }
  407.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  408.  
  409.    pb->pb_DevNode.lib_OpenCnt--;
  410.    ReleaseSemaphore(&pb->pb_Lock);
  411.  
  412.    return rv;
  413. }
  414. /*E*/
  415.  
  416.    /*
  417.    ** close device
  418.    */
  419. /*F*/ PUBLIC ASM SAVEDS BPTR DevClose(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  420. {
  421.    BPTR seglist;
  422.    struct BufferManagement *bm;
  423.  
  424.    d2(("entered\n"));
  425.  
  426.    ObtainSemaphore(&pb->pb_Lock);
  427.  
  428.       /* invalidate IO request block */
  429.    ior->ios2_Req.io_Device = (struct Device *)-1;
  430.    ior->ios2_Req.io_Unit = (struct Unit *)-1;
  431.  
  432.       /* search and free BuffMgmt structure */
  433.    for(bm = (struct BufferManagement *)pb->pb_BufferManagement.lh_Head;
  434.        bm->bm_Node.mln_Succ; bm = (struct BufferManagement *)bm->bm_Node.mln_Succ)
  435.       if (bm == ior->ios2_BufferManagement)
  436.       {
  437.          Remove((struct Node*)bm);
  438.          FreeVec(bm);
  439.          break;
  440.       }
  441.  
  442.    pb->pb_DevNode.lib_OpenCnt--;
  443.  
  444.    ReleaseSemaphore(&pb->pb_Lock);
  445.  
  446.    if (pb->pb_DevNode.lib_Flags & LIBF_DELEXP)
  447.       seglist = DevExpunge(pb);
  448.    else
  449.       seglist = 0;
  450.  
  451.    return seglist;
  452. }
  453. /*E*/
  454.  
  455.  
  456. /*F*/ PUBLIC ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR)
  457. {
  458.    BPTR seglist;
  459.    ULONG sigb;
  460.  
  461.    d2(("entered\n"));
  462.  
  463.    if (pb->pb_DevNode.lib_OpenCnt)
  464.    {
  465.       pb->pb_DevNode.lib_Flags |= LIBF_DELEXP;
  466.       seglist = 0;
  467.    }
  468.    else
  469.    {
  470.          /* detach device from system list */
  471.       Remove((struct Node*)pb);
  472.  
  473.          /* stop the servr task */
  474.       d2(("killing server task\n"));
  475.       pb->pb_Task = FindTask(0L);
  476.          /* We must allocate a new signal, as we don't know in whose
  477.          ** context we're running. If we get no signal, we poll
  478.          ** for the server-exits flag.
  479.          */
  480.       sigb = AllocSignal(-1);
  481.       pb->pb_ServerStoppedSigMask = (sigb == -1) ? 0 : (1<<sigb);
  482.       Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_C);
  483.       if (pb->pb_ServerStoppedSigMask)
  484.       {
  485.          Wait(pb->pb_ServerStoppedSigMask);
  486.          FreeSignal(sigb);
  487.       }
  488.       else
  489.       {
  490.          while(!(pb->pb_Flags & PLIPF_SERVERSTOPPED))
  491.             Delay(10);
  492.       }
  493.       d2(("server task has gone\n"));
  494.  
  495.          /* clean up track */
  496.       freetracktypes(pb);
  497.  
  498.       CloseLibrary(UtilityBase);
  499.       CloseLibrary(DOSBase);
  500.  
  501.          /* save seglist for return value */
  502.       seglist = (long)pb->pb_SegList;
  503.  
  504.          /* return memory
  505.          **
  506.          ** NO FURTHER ACCESS TO PLIPBase ALLOWED!
  507.          */
  508.       FreeMem( ((char *) pb) - pb->pb_DevNode.lib_NegSize,
  509.          (ULONG)(pb->pb_DevNode.lib_PosSize + pb->pb_DevNode.lib_NegSize));
  510.    }
  511.  
  512.    return seglist;
  513. }
  514. /*E*/
  515.  
  516.    /*
  517.    ** initiate io command (1st level dispatcher)
  518.    */
  519. /*F*/ static INLINE VOID DevForwardIO(BASEPTR, struct IOSana2Req *ios2)
  520. {
  521.    d(("forwarding request %ld\n", ios2->ios2_Req.io_Command));
  522.  
  523.    /* request is no longer of type "quick i/o" */
  524.    ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  525.    PutMsg(pb->pb_ServerPort, (struct Message*)ios2);
  526. }
  527. /*E*/
  528. /*F*/ PUBLIC VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2)
  529. {
  530.    d(("cmd = %ld, error = %ld, wireerror = %ld\n", ios2->ios2_Req.io_Command, ios2->ios2_Req.io_Error,ios2->ios2_WireError));
  531.  
  532.                   /* if this command was done asynchonously, we must
  533.                   ** reply the request
  534.                   */
  535.    if(!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK))
  536.       ReplyMsg((struct Message *)ios2);
  537.    else           /* otherwise just mark it as done */
  538.       ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  539. }
  540. /*E*/
  541. /*F*/ PUBLIC ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR)
  542. {
  543.       /* mark request as active */
  544.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  545.    ios2->ios2_Req.io_Error = S2ERR_NO_ERROR;
  546.    ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  547.  
  548.    d(("cmd = %ld\n",ios2->ios2_Req.io_Command));
  549.  
  550.       /*
  551.       ** 1st level command dispatcher
  552.       **
  553.       ** Here we decide wether we can process the request immediately avoiding
  554.       ** a task switch. This is called "Quick I/O" and signalled to DoIO()
  555.       ** by setting the node type of the request to NT_REPLYMSG (see TermIO()).
  556.       **
  557.       ** Otherwise, we clear the SANA2IOF_QUICK flag and forward the request to
  558.       ** the server. We may NEVER again access the request structure after
  559.       ** the PutMsg()! The server - running at a high priority - will peempt
  560.       ** us and might complety satisfy the request before we will be wakened up
  561.       ** again.
  562.       ** The same goes for those requests that we put into the server's queue.
  563.       */
  564.    switch(ios2->ios2_Req.io_Command)
  565.    {
  566.       case CMD_READ:
  567.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  568.          {
  569.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  570.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  571.          }
  572.          else if (ios2->ios2_BufferManagement == NULL)
  573.          {
  574.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  575.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  576.          }
  577.          else
  578.          {
  579.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  580.             ObtainSemaphore(&pb->pb_ReadListSem);
  581.             AddTail((struct List*)&pb->pb_ReadList, (struct Node*)ios2);
  582.             ReleaseSemaphore(&pb->pb_ReadListSem);
  583.             ios2 = NULL;
  584.          }
  585.       break;
  586.  
  587.       case CMD_WRITE:
  588.       case S2_BROADCAST:
  589.          if (ios2->ios2_Req.io_Flags & SANA2IOF_RAW)
  590.          {
  591.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  592.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  593.          }
  594.          else if(ios2->ios2_DataLength > pb->pb_MTU)
  595.          {
  596.             ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  597.          }
  598.          else if (ios2->ios2_BufferManagement == NULL)
  599.          {
  600.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  601.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  602.          }
  603.          else if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  604.          {
  605.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  606.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  607.          }
  608.          else
  609.          {
  610.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  611.             ios2->ios2_Req.io_Error = 0;
  612.             ObtainSemaphore(&pb->pb_WriteListSem);
  613.             AddTail((struct List*)&pb->pb_WriteList, (struct Node*)ios2);
  614.             ReleaseSemaphore(&pb->pb_WriteListSem);
  615.             Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_F);
  616.             ios2 = NULL;
  617.          }
  618.       break;
  619.  
  620.       case S2_ONLINE:
  621.       case S2_OFFLINE:
  622.       case S2_CONFIGINTERFACE:   /* forward request */
  623.          DevForwardIO(pb, ios2);
  624.          ios2 = NULL;
  625.       break;
  626.  
  627.       case S2_GETSTATIONADDRESS:
  628.          memcpy(ios2->ios2_SrcAddr, pb->pb_SrcAddr, PLIP_ADDRFIELDSIZE);
  629.          memcpy(ios2->ios2_DstAddr, pb->pb_DstAddr, PLIP_ADDRFIELDSIZE);
  630.       break;
  631.          
  632.       case S2_DEVICEQUERY:
  633.       {
  634.          struct Sana2DeviceQuery *devquery;
  635.  
  636.          devquery = ios2->ios2_StatData;
  637.          devquery->DevQueryFormat = 0;        /* "this is format 0" */
  638.          devquery->DeviceLevel = 0;           /* "this spec defines level 0" */
  639.          
  640.          if (devquery->SizeAvailable >= 18) devquery->AddrFieldSize = PLIP_ADDRFIELDSIZE;
  641.          if (devquery->SizeAvailable >= 22) devquery->MTU           = pb->pb_MTU;
  642.          if (devquery->SizeAvailable >= 26) devquery->BPS           = pb->pb_ReportBPS;
  643.          if (devquery->SizeAvailable >= 30) devquery->HardwareType  = S2WireType_PLIP;
  644.          
  645.          devquery->SizeSupplied = min((int)devquery->SizeAvailable, 30);
  646.       }
  647.       break;
  648.          
  649.       case S2_ONEVENT:
  650.          /* Two special cases. S2EVENT_ONLINE and S2EVENT_OFFLINE are supposed to
  651.             retun immediately if we are already in the state that they are waiting
  652.             for. */
  653.          if (((ios2->ios2_WireError & S2EVENT_ONLINE) && !(pb->pb_Flags & PLIPF_OFFLINE)) ||
  654.              ((ios2->ios2_WireError & S2EVENT_OFFLINE) && (pb->pb_Flags & PLIPF_OFFLINE)))
  655.          {
  656.             ios2->ios2_Req.io_Error = 0;
  657.             ios2->ios2_WireError &= (S2EVENT_ONLINE|S2EVENT_OFFLINE);
  658.             DevTermIO(pb,ios2);
  659.             ios2 = NULL;
  660.          }
  661.          else if ((ios2->ios2_WireError & (S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|
  662.                                S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE|S2EVENT_SOFTWARE))
  663.                   != ios2->ios2_WireError)
  664.          {
  665.             /* we cannot handle such events */
  666.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  667.             ios2->ios2_WireError = S2WERR_BAD_EVENT;
  668.          }
  669.          else
  670.          {
  671.             /* Queue anything else */
  672.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  673.             ObtainSemaphore(&pb->pb_EventListSem);
  674.             AddTail((struct List*)&pb->pb_EventList, (struct Node*)ios2);
  675.             ReleaseSemaphore(&pb->pb_EventListSem);
  676.             ios2 = NULL;
  677.          }
  678.       break;
  679.  
  680.       /* --------------- stats support ----------------------- */
  681.  
  682.       case S2_TRACKTYPE:
  683.          if (!addtracktype(pb, ios2->ios2_PacketType))
  684.          {
  685.             ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  686.          }
  687.       break;
  688.  
  689.       case S2_UNTRACKTYPE:
  690.          if (!remtracktype(pb, ios2->ios2_PacketType))
  691.          {
  692.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  693.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  694.          }
  695.       break;
  696.  
  697.       case S2_GETTYPESTATS:
  698.          if (!gettrackrec(pb, ios2->ios2_PacketType, (struct Sana2PacketTypeStats *)ios2->ios2_StatData))
  699.          {
  700.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  701.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  702.          }
  703.       break;
  704.  
  705.       case S2_READORPHAN:
  706.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  707.          {
  708.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  709.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  710.          }
  711.          else if (ios2->ios2_BufferManagement == NULL)
  712.          {
  713.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  714.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  715.          }
  716.          else
  717.          {                       /* Enqueue it to the orphan-reader-list */
  718.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  719.             ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  720.             AddTail((struct List*)&pb->pb_ReadOrphanList, (struct Node*)ios2);
  721.             ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  722.             ios2 = NULL;
  723.          }
  724.       break;
  725.  
  726.       case S2_GETGLOBALSTATS:
  727.          memcpy(ios2->ios2_StatData, &pb->pb_DevStats, sizeof(struct Sana2DeviceStats));
  728.       break;
  729.  
  730.       case S2_GETSPECIALSTATS:
  731.       {
  732.          struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  733.  
  734.          if (pb->pb_ExtFlags & PLIPEF_NOSPECIALSTATS)
  735.          {
  736.             s2ssh->RecordCountSupplied = 0;
  737.          }
  738.          else
  739.          {
  740.             s2ssh->RecordCountSupplied = s2ssh->RecordCountMax > S2SS_COUNT ?
  741.                                           S2SS_COUNT : s2ssh->RecordCountMax;
  742.             CopyMem(pb->pb_SpecialStats, (void*)(s2ssh+1),
  743.                         s2ssh->RecordCountSupplied*sizeof(struct Sana2SpecialStatRecord));
  744.          }
  745.       }
  746.       break;
  747.  
  748.       /* --------------- unsupported requests -------------------- */
  749.  
  750.          /* all standard commands we don't support */
  751.       case CMD_RESET:
  752.       case CMD_UPDATE:
  753.       case CMD_CLEAR:
  754.       case CMD_STOP:
  755.       case CMD_START:
  756.       case CMD_FLUSH:
  757.          ios2->ios2_Req.io_Error = IOERR_NOCMD;
  758.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  759.       break;
  760.  
  761.          /* other commands (SANA-2) we don't support */
  762.       /*case S2_ADDMULTICASTADDRESS:*/
  763.       /*case S2_DELMULTICASTADDRESS:*/
  764.       /*case S2_MULTICAST:*/
  765.       default:
  766.          ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  767.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  768.       break;
  769.    }
  770.  
  771.    if (ios2) DevTermIO(pb, ios2);
  772.  
  773.    return;
  774. }
  775. /*E*/
  776.  
  777.    /*
  778.    ** stop io-command
  779.    */
  780. /*F*/ PUBLIC ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  781. {
  782.    BOOL is;
  783.    LONG rc = 0;
  784.  
  785.    d(("cmd = %ld\n",ior->ios2_Req.io_Command));
  786.  
  787.    ObtainSemaphore(&pb->pb_WriteListSem);
  788.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_WriteList)) abort(pb,ior);
  789.    ReleaseSemaphore(&pb->pb_WriteListSem);
  790.    if (is) goto leave;
  791.  
  792.    ObtainSemaphore(&pb->pb_ReadListSem);
  793.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadList)) abort(pb,ior);
  794.    ReleaseSemaphore(&pb->pb_ReadListSem);
  795.    if (is) goto leave;
  796.  
  797.    ObtainSemaphore(&pb->pb_EventListSem);
  798.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_EventList)) abort(pb,ior);
  799.    ReleaseSemaphore(&pb->pb_EventListSem);
  800.    if (is) goto leave;
  801.  
  802.    ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  803.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadOrphanList)) abort(pb,ior);
  804.    ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  805.    if (is) goto leave;
  806.  
  807.    rc = -1;
  808.  
  809. leave:
  810.    return rc;
  811. }
  812. /*E*/
  813.  
  814.